package com.by.auth;


import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

@Component
public class TokenTemplate {

    /**
     * 密钥
     */
    @Value("${token.secret}")
    String secret;// 密钥

    /**
     * 有效期 单位：秒
     */
    @Value("${token.validTime}")
    long validTime;

    /**
     * 默认有效期 单位：秒
     */
    private final long DEFAULT_VALID_TIME = 30*60*1000; // 默认有效期30分钟

    /**
     * 生成token
     * @param payload 用户信息
     * @return token字符串
     */
    public String generateToken(Map payload) {
        String token = JWT.create()
                .withHeader(getHeader())
                .withPayload(payload)
                .withExpiresAt(getValidDate())
                .sign(Algorithm.HMAC256(getSecret()));
        return token;
    }



    /**
     * 验证token
     * @param token token字符串
     * @return 验证结果
     */
    public ValidResult validate(String token){
          if (token == null || "".equals(token))
              return new ValidResult(0, "token为空", null);
        DecodedJWT decodedJWT = null;
        try {
            JWT.require(Algorithm.HMAC256(secret))
                    .build()
                    .verify(token);
        }catch (TokenExpiredException e){
            return new ValidResult(0, "token已过期", null);
        }catch (Exception e){
            return new ValidResult(1, "token无效", null);
        }
        // 验证通过
        Map<String, Claim> map = decodedJWT.getClaims();
          return new ValidResult(2, "验证成功", convert(map));
    }


    /**
     * 刷新token
     * @param token
     * @return
     */
    public String refreshToken(String token) {
        // 验证token
        ValidResult result = validate(token);
        if (result.getCode() == 1) {// token无效
            return null;
        }else if (result.getCode() == 0) {// token过期
            DecodedJWT decodedJWT = JWT.decode(token);
            //获取用户信息
            Map<String, Claim> map = decodedJWT.getClaims();
            //生成新token
            return generateToken(convert(map));
        }
        // 验证通过
        Map map = result.getUser();
        // 生成新token
        return generateToken(map);
    }


    /**
     * 转换Claim到Map
     * @param map
     * @return
     */
    Map<String,String> convert(Map<String,Claim> map){
        Map<String,String> tmp = new HashMap<>();
        map.forEach((k,v)->{
            tmp.put(k,v.asString());
        });
        return tmp;
    }

    /**
     * 获取有效期
     * @return
     */
    Date getValidDate() {
        long time = System.currentTimeMillis()+getValidTime();
        Date now = new Date(time);
        return now;
    }


    /**
     * 头部
     *
     * @return
     */
    Map getHeader() {
        Map map = new HashMap();
        map.put("typ", "JWT");
        map.put("alg", "HS256");
        return map;
    }

    public String getSecret() {
        if (secret == null) {
            secret = UUID.randomUUID().toString();
        }
        return secret;
    }

    public void setSecret(String secret) {
        this.secret = secret;
    }

    public long getValidTime() {
        if (validTime == 0) {
            validTime = DEFAULT_VALID_TIME;
        }
        return validTime;
    }

    public void setValidTime(long validTime) {
        this.validTime = validTime;
    }
}
